home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / lfs / lfsDesc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-09  |  14.8 KB  |  504 lines

  1. /* 
  2.  * lfsDesc.c --
  3.  *
  4.  *    File descriptor management routines for LFS. The routine in 
  5.  *    this module provide the interface for file descriptors I/O 
  6.  *      and allocation for a LFS file system.   The implementation uses
  7.  *    the file system block cache to cache groups of descriptors and
  8.  *    provide write buffering. 
  9.  *
  10.  * Copyright 1989 Regents of the University of California
  11.  * Permission to use, copy, modify, and distribute this
  12.  * software and its documentation for any purpose and without
  13.  * fee is hereby granted, provided that the above copyright
  14.  * notice appear in all copies.  The University of California
  15.  * makes no representations about the suitability of this
  16.  * software for any purpose.  It is provided "as is" without
  17.  * express or implied warranty.
  18.  */
  19.  
  20. #ifndef lint
  21. static char rcsid[] = "$Header: /sprite/src/kernel/lfs/RCS/lfsDesc.c,v 1.8 91/08/08 17:43:44 mendel Exp $ SPRITE (Berkeley)";
  22. #endif /* not lint */
  23.  
  24. #include <sprite.h>
  25. #include <lfs.h>
  26. #include <lfsInt.h>
  27. #include <lfsDesc.h>
  28. #include <lfsDescMap.h>
  29. #include <fs.h>
  30. #include <fsdm.h>
  31.  
  32.  
  33. /*
  34.  * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  35.  * Start of routines exported to higher levels of the file system.
  36.  * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  37.  */
  38.  
  39.  
  40. /*
  41.  *----------------------------------------------------------------------
  42.  *
  43.  * Lfs_FileDescFetch() --
  44.  *
  45.  *    Fetch the specified file descriptor from the file system and 
  46.  *    store it in *fileDescPtr.
  47.  *
  48.  * Results:
  49.  *    An error if could not read the file descriptor from disk or is not
  50.  *    allocated.
  51.  *
  52.  * Side effects:
  53.  *    A block of descriptors may be read into the cache.
  54.  *
  55.  *----------------------------------------------------------------------
  56.  */
  57.  
  58. ReturnStatus
  59. Lfs_FileDescFetch(domainPtr, fileNumber, fileDescPtr)
  60.      Fsdm_Domain     *domainPtr;    /* Domain to fetch file descriptor. */
  61.      int        fileNumber;     /* Number of file descriptor to fetch.*/
  62.      Fsdm_FileDescriptor *fileDescPtr;    /* File descriptor structure to fetch.*/
  63. {
  64.     Lfs    *lfsPtr = LfsFromDomainPtr(domainPtr);
  65.     LfsFileDescriptor    *descPtr;
  66.     Fscache_Block        *blockPtr;
  67.     ReturnStatus    status;
  68.     LfsDiskAddr           diskAddr;
  69.     int        i, cacheFlags;
  70.     Boolean    found;
  71.  
  72.     LFS_STATS_INC(lfsPtr->stats.desc.fetches);
  73.     status = LfsDescMapGetDiskAddr(lfsPtr, fileNumber, &diskAddr);
  74.     if (status != SUCCESS) {
  75.     return status;
  76.     }
  77.     cacheFlags = FSCACHE_DESC_BLOCK;
  78.     if (LfsIsCleanerProcess(lfsPtr)) {
  79.     cacheFlags |= FSCACHE_CANT_BLOCK;
  80.     }
  81.     /*
  82.      * See if the value is in the descriptor block cache. If it is not 
  83.      * then read it in.
  84.      */
  85.     Fscache_FetchBlock(&lfsPtr->descCache.handle.cacheInfo, 
  86.               LfsDiskAddrToOffset(diskAddr), cacheFlags,
  87.                &blockPtr, &found);
  88.     if (!found) {
  89.     LFS_STATS_INC(lfsPtr->stats.desc.fetchCacheMiss);
  90.     status = LfsReadBytes(lfsPtr, diskAddr, 
  91.         lfsPtr->fileLayout.params.descPerBlock * sizeof(*descPtr),
  92.         blockPtr->blockAddr);
  93. #ifdef ERROR_CHECK
  94.      LfsCheckRead(lfsPtr, diskAddr, 
  95.         lfsPtr->fileLayout.params.descPerBlock * sizeof(*descPtr));
  96. #endif
  97.     if (status != SUCCESS) {
  98.         printf( "Could not read in file descriptor\n");
  99.         Fscache_UnlockBlock(blockPtr, 0, -1, 0, FSCACHE_DELETE_BLOCK);
  100.         return status;
  101.     }
  102.     }
  103.     descPtr = (LfsFileDescriptor *) (blockPtr->blockAddr);
  104.     for (i = 0; i < lfsPtr->fileLayout.params.descPerBlock; i++) {
  105.     if (!(descPtr->common.flags & FSDM_FD_ALLOC)) {
  106.         break;
  107.     }
  108.     if (descPtr->fileNumber == fileNumber) {
  109.          LFS_STATS_INC(lfsPtr->stats.desc.goodFetch);
  110.          LFS_STATS_ADD(lfsPtr->stats.desc.fetchSearched,i);
  111.          bcopy((char *) &(descPtr->common), (char *)fileDescPtr,
  112.             sizeof(descPtr->common));
  113.          status = LfsDescMapGetAccessTime(lfsPtr, fileNumber,
  114.                 &(fileDescPtr->accessTime));
  115.          if (status != SUCCESS) {
  116.           LfsError(lfsPtr, status, "Can't get access time.\n");
  117.          }
  118.         Fscache_UnlockBlock(blockPtr, 0, -1, FS_BLOCK_SIZE, 0);
  119.         return SUCCESS;
  120.     }
  121.     descPtr++;
  122.     }
  123.     Fscache_UnlockBlock(blockPtr, 0, -1, 0, FSCACHE_DELETE_BLOCK);
  124.     panic("Descriptor map foulup, can't find file %d at %d\n", fileNumber,
  125.             LfsDiskAddrToOffset(diskAddr));
  126.     return FS_FILE_NOT_FOUND;
  127.  
  128. }
  129.  
  130.  
  131. /*
  132.  *----------------------------------------------------------------------
  133.  *
  134.  * Lfs_FileDescStore() --
  135.  *    Store the given file descriptor back into the file system block
  136.  *    where it came from.  
  137.  *
  138.  * Results:
  139.  *    An error if could not read the file descriptor from disk or is not
  140.  *    allocated.
  141.  *
  142.  * Side effects:
  143.  *    A block of descriptors may be read into the cache.
  144.  *
  145.  *----------------------------------------------------------------------
  146.  */
  147.  
  148. ReturnStatus
  149. Lfs_FileDescStore(domainPtr, handlePtr, fileNumber, fileDescPtr, forceOut)
  150.     register Fsdm_Domain *domainPtr;    /* Domain to store the file 
  151.                      * descriptor into. */
  152.     Fsio_FileIOHandle    *handlePtr;
  153.     int            fileNumber;     /* Number of file descriptor to 
  154.                        store.*/
  155.     Fsdm_FileDescriptor    *fileDescPtr;     /* File descriptor to store. */
  156.     Boolean        forceOut;  /* Force the change to disk. */
  157. {
  158.     Lfs    *lfsPtr = LfsFromDomainPtr(domainPtr);
  159.     ReturnStatus    status = SUCCESS;
  160.  
  161.     LFS_STATS_INC(lfsPtr->stats.desc.stores);
  162.     if (fileDescPtr->flags & FSDM_FD_FREE) {
  163.     LFS_STATS_INC(lfsPtr->stats.desc.freeStores);
  164.     return SUCCESS;
  165.     }
  166.     if (fileDescPtr->flags & FSDM_FD_ACCESSTIME_DIRTY) {
  167.      status = LfsDescMapSetAccessTime(lfsPtr, fileNumber, 
  168.                  fileDescPtr->accessTime);
  169.       if (status != SUCCESS) {
  170.           LfsError(lfsPtr, status, "Can't update descriptor map.\n");
  171.           }
  172.       fileDescPtr->flags &= ~FSDM_FD_ACCESSTIME_DIRTY;
  173.       LFS_STATS_INC(lfsPtr->stats.desc.accessTimeUpdate);
  174.     }
  175.     if (fileDescPtr->flags & FSDM_FD_DIRTY) {
  176.     LFS_STATS_INC(lfsPtr->stats.desc.dirtyList);
  177.     Fscache_PutFileOnDirtyList(&handlePtr->cacheInfo, 
  178.                 FSCACHE_FILE_DESC_DIRTY);
  179.     }
  180.     return status;
  181. }
  182.  
  183. /*
  184.  *----------------------------------------------------------------------
  185.  *
  186.  * Lfs_FileTrunc --
  187.  *
  188.  *      Shorten a file to length bytes.  This updates the descriptor
  189.  *      and may free blocks and indirect blocks from the end of the file.
  190.  *
  191.  * Results:
  192.  *      Error if had problem with indirect blocks, otherwise SUCCESS.
  193.  *
  194.  * Side effects:
  195.  *      May modify the truncateVersion number.
  196.  *    Any allocated blocks after the given size are deleted.
  197.  *
  198.  *----------------------------------------------------------------------
  199.  */
  200.  
  201. ReturnStatus
  202. Lfs_FileTrunc(domainPtr, handlePtr, size, delete)
  203.     Fsdm_Domain        *domainPtr;
  204.     Fsio_FileIOHandle   *handlePtr;     /* File to truncate. */
  205.     int                 size;           /* Size to truncate the file to. */
  206.     Boolean        delete;        /* TRUE if Truncate for delete. */
  207. {
  208.     Lfs    *lfsPtr = LfsFromDomainPtr(domainPtr);
  209.     Fsdm_FileDescriptor    *descPtr;
  210.     ReturnStatus    status = SUCCESS;
  211.     int            newLastByte;
  212.  
  213.     if (size < 0) {
  214.     return(GEN_INVALID_ARG);
  215.     }
  216.     LFS_STATS_INC(lfsPtr->stats.desc.truncs);
  217.  
  218.     descPtr = handlePtr->descPtr;
  219.  
  220.     newLastByte = size - 1;
  221.     if (descPtr->lastByte <= newLastByte) {
  222.     status = SUCCESS;
  223.     goto exit;
  224.     }
  225.  
  226.     /*
  227.      * Pause the write back during the truncate to sync access to
  228.      * file index.
  229.      */
  230.     Fscache_PreventWriteBacks(&handlePtr->cacheInfo);
  231.     status = LfsFile_TruncIndex(lfsPtr, handlePtr, size);
  232.     if (status == SUCCESS) {
  233.     if (size == 0) {
  234.         int    newVersion;
  235.         LFS_STATS_INC(lfsPtr->stats.desc.truncSizeZero);
  236.         status = LfsDescMapIncVersion(lfsPtr, 
  237.             handlePtr->hdr.fileID.minor, &newVersion);
  238.     }
  239.     descPtr->lastByte = newLastByte;
  240.     descPtr->descModifyTime = Fsutil_TimeInSeconds();
  241.     if (delete) {
  242.         /*
  243.          * XXX - need sync here. 
  244.          */
  245.         descPtr->flags &= ~FSDM_FD_DIRTY;
  246.     } else {
  247.         descPtr->flags |= FSDM_FD_SIZE_DIRTY;
  248.     }
  249.     }
  250.     Fscache_AllowWriteBacks(&handlePtr->cacheInfo);
  251. exit:
  252.     if (delete) { 
  253.     LFS_STATS_INC(lfsPtr->stats.desc.delete);
  254.     /*
  255.      * XXX - need sync here. 
  256.      */
  257.     descPtr->flags &= ~FSDM_FD_DIRTY;
  258.     status = Fscache_RemoveFileFromDirtyList(&handlePtr->cacheInfo);
  259.     } else {
  260.     if (descPtr->flags & FSDM_FD_DIRTY) {
  261.         status = Fscache_PutFileOnDirtyList(&handlePtr->cacheInfo, 
  262.                 FSCACHE_FILE_DESC_DIRTY);
  263.     }
  264.     }
  265.     return status;
  266. }
  267.  
  268. /*
  269.  *----------------------------------------------------------------------
  270.  *
  271.  * Lfs_FileDescInit() --
  272.  *
  273.  *    Initialize a new file descriptor.
  274.  *
  275.  * Results:
  276.  *    SUCCESS
  277.  *
  278.  * Side effects:
  279.  *    The file decriptor is initialized.
  280.  *
  281.  *----------------------------------------------------------------------
  282.  */
  283. /*ARGSUSED*/
  284. ReturnStatus
  285. Lfs_FileDescInit(domainPtr, fileNumber, type, permissions, uid, gid, fileDescPtr)
  286.     Fsdm_Domain     *domainPtr;    /* Domain of the file */
  287.     int            fileNumber;     /* Number of file descriptor */
  288.     int            type;        /* Type of the file */
  289.     int            permissions;    /* Permission bits for the file */
  290.     int            uid;        /* Owner ID for the file */
  291.     int            gid;        /* Group ID for the file */
  292.     Fsdm_FileDescriptor    *fileDescPtr;    /* File descriptor structure to
  293.                        initialize. */
  294. {
  295.     register int index;
  296.     LFS_STATS_INC((LfsFromDomainPtr(domainPtr))->stats.desc.inits);
  297.  
  298.     fileDescPtr->magic = FSDM_FD_MAGIC;
  299.     fileDescPtr->flags = FSDM_FD_ALLOC|FSDM_FD_DIRTY;
  300.     fileDescPtr->fileType = type;
  301.     fileDescPtr->permissions = permissions;
  302.     fileDescPtr->uid = uid;
  303.     fileDescPtr->gid = gid;
  304.     fileDescPtr->lastByte = -1;
  305.     fileDescPtr->lastByteXtra = 0;
  306.     fileDescPtr->firstByte = -1;
  307.     fileDescPtr->userType = FS_USER_TYPE_UNDEFINED;
  308.     fileDescPtr->numLinks = 1;
  309.  
  310.     /*
  311.      * Clear out device info.  It is set up properly by the make-device routine.
  312.      */
  313.     fileDescPtr->devServerID = -1;
  314.     fileDescPtr->devType = -1;
  315.     fileDescPtr->devUnit = -1;
  316.  
  317.     /*
  318.      * Set the time stamps.  These times should come from the client.
  319.      */
  320.     fileDescPtr->createTime = Fsutil_TimeInSeconds();
  321.     fileDescPtr->accessTime = fileDescPtr->createTime;
  322.     fileDescPtr->descModifyTime = fileDescPtr->createTime;
  323.     fileDescPtr->dataModifyTime = fileDescPtr->createTime;
  324.  
  325.     for (index = 0; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
  326.     fileDescPtr->direct[index] = FSDM_NIL_INDEX;
  327.     }
  328.     for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
  329.     fileDescPtr->indirect[index] = FSDM_NIL_INDEX;
  330.     }
  331.     fileDescPtr->numKbytes = 0;
  332.     /*
  333.      * Give this new file a new version number.  The increment is by 2 to
  334.      * ensure that a client invalidates any cache blocks associated with
  335.      * the previous incarnation of the file.  Remember that when a client
  336.      * opens for writing a version number 1 greater means that its old
  337.      * cache blocks are still ok, and also remember that clients with
  338.      * clean blocks are not told when a file is deleted.
  339.      */
  340.     fileDescPtr->version = LfsGetCurrentTimestamp(LfsFromDomainPtr(domainPtr));
  341.     return(SUCCESS);
  342. }
  343.  
  344. /*
  345.  * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  346.  * End of routines exported to higher levels of the file system.
  347.  * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  348.  *
  349.  * Start of LFS private routines. 
  350.  */
  351.  
  352. /*
  353.  *----------------------------------------------------------------------
  354.  *
  355.  * LfsDescCacheInit --
  356.  *
  357.  *    Initialize the descriptor cache for a file system.
  358.  *
  359.  * Results:
  360.  *    None.
  361.  *
  362.  * Side effects:
  363.  *    None.
  364.  *
  365.  *----------------------------------------------------------------------
  366.  */
  367. void
  368. LfsDescCacheInit(lfsPtr)
  369.     Lfs        *lfsPtr;
  370. {
  371.     Fscache_Attributes        attr;
  372.     /*
  373.      * Initialize the file handle used to cache descriptor blocks.
  374.      */
  375.  
  376.     bzero((char *)(&lfsPtr->descCache.handle),sizeof(lfsPtr->descCache.handle));
  377.     lfsPtr->descCache.handle.hdr.fileID.serverID = rpc_SpriteID;
  378.     lfsPtr->descCache.handle.hdr.fileID.major = lfsPtr->domainPtr->domainNumber;
  379.     lfsPtr->descCache.handle.hdr.fileID.minor = 0;
  380.     lfsPtr->descCache.handle.hdr.fileID.type = FSIO_LCL_FILE_STREAM;
  381.     lfsPtr->descCache.handle.descPtr = (Fsdm_FileDescriptor *)NIL;
  382.  
  383.  
  384.     bzero((Address)&attr, sizeof(attr));
  385.     attr.lastByte = 0x7fffffff;
  386.     Fscache_FileInfoInit(&lfsPtr->descCache.handle.cacheInfo,
  387.             (Fs_HandleHeader *) &lfsPtr->descCache.handle,
  388.             0, TRUE, &attr, lfsPtr->domainPtr->backendPtr);
  389.  
  390. }
  391.  
  392. /*
  393.  *----------------------------------------------------------------------
  394.  *
  395.  * LfsDescCacheDestory --
  396.  *
  397.  *    Destory the descriptor cache for a file system.
  398.  *
  399.  * Results:
  400.  *    None.
  401.  *
  402.  * Side effects:
  403.  *    None.
  404.  *
  405.  *----------------------------------------------------------------------
  406.  */
  407. void
  408. LfsDescCacheDestory(lfsPtr)
  409.     Lfs        *lfsPtr;
  410. {
  411.  
  412.     Fscache_FileInvalidate(&lfsPtr->descCache.handle.cacheInfo, 0, 
  413.         FSCACHE_LAST_BLOCK);
  414.  
  415. }
  416.  
  417. /*
  418.  *----------------------------------------------------------------------
  419.  *
  420.  * LfsDescCacheBlockInit --
  421.  *
  422.  *    Initialize a block into the descriptor cache for a file system.
  423.  *
  424.  * Results:
  425.  *    NIL if the block couldn't be initialized. A clientData otherwise. 
  426.  *
  427.  * Side effects:
  428.  *    Cache block is fetched and held.
  429.  *
  430.  *----------------------------------------------------------------------
  431.  */
  432.  
  433. ClientData
  434. LfsDescCacheBlockInit(lfsPtr, diskBlockAddr, cantBlock, blockStartPtr)
  435.     Lfs        *lfsPtr;    /* File system. */
  436.     LfsDiskAddr    diskBlockAddr;    /* Descriptor cache block address. */
  437.     Boolean     cantBlock;    /* TRUE if process can`t block. */
  438.     char    **blockStartPtr;    /* OUT: pointer to lock's contents. */
  439. {
  440.     Fscache_Block    *blockPtr;
  441.     int            blockNum;
  442.     Boolean    found;
  443.  
  444.     blockNum = LfsDiskAddrToOffset(diskBlockAddr);
  445.     Fscache_FetchBlock(&lfsPtr->descCache.handle.cacheInfo,
  446.         blockNum, (FSCACHE_DESC_BLOCK|FSCACHE_CANT_BLOCK| (cantBlock ? FSCACHE_DONT_BLOCK:0)),
  447.             &blockPtr, &found);
  448.     if (blockPtr == (Fscache_Block *) NIL) {
  449.     return (ClientData) blockPtr;
  450.     }
  451.     if (!found) {
  452.     if ((*blockStartPtr) != (char *) NIL) {
  453.         bcopy(*blockStartPtr, blockPtr->blockAddr,
  454.            lfsPtr->fileLayout.params.descPerBlock * 
  455.             LFS_FILE_DESC_SIZE);
  456.     } else {
  457.         bzero(blockPtr->blockAddr, lfsPtr->fileLayout.params.descPerBlock * 
  458.             LFS_FILE_DESC_SIZE);
  459.     }
  460.     Fscache_IODone(blockPtr);
  461.     } else {
  462. #ifdef ERROR_CHECK
  463.     if (((*blockStartPtr) != (char *) NIL) && 
  464.         (bcmp(*blockStartPtr, blockPtr->blockAddr, 
  465.         lfsPtr->fileLayout.params.descPerBlock * LFS_FILE_DESC_SIZE) 
  466.         != 0)) {
  467.         panic("LfsDescCacheBlockInit found wrong block\n");
  468.     }
  469. #endif
  470.     }
  471.     if (*blockStartPtr == (char *) NIL) { 
  472.     *blockStartPtr = blockPtr->blockAddr;
  473.     }
  474.     return (ClientData) blockPtr;
  475. }
  476.  
  477.  
  478. /*
  479.  *----------------------------------------------------------------------
  480.  *
  481.  * LfsDescCacheBlockRelease --
  482.  *
  483.  *    Release a desc cache block return by LfsDescCacheBlockInit.
  484.  *
  485.  * Results:
  486.  *    void
  487.  *
  488.  * Side effects:
  489.  *
  490.  *----------------------------------------------------------------------
  491.  */
  492.  
  493. void
  494. LfsDescCacheBlockRelease(lfsPtr, clientData, deleteBlock)
  495.     Lfs        *lfsPtr;
  496.     ClientData    clientData;
  497.     Boolean    deleteBlock;     /* TRUE if block should be deleted. */
  498. {
  499.     Fscache_Block    *blockPtr = (Fscache_Block *) clientData;
  500.     Fscache_UnlockBlock(blockPtr,(unsigned)0, -1, FS_BLOCK_SIZE, 
  501.         deleteBlock ? FSCACHE_DELETE_BLOCK : 0);
  502. }
  503.  
  504.